package mysql

import (
	"log"
	"reflect"
	"strconv"
)

type DeviceBaseInfoMapper struct {
	ds *DataMysqlSourceClinet
}

type DeviceState struct {
	Id        int64  `db:"id"`
	DeviceId  string `db:"device_id"`
	OnlineFlg string `db:"online_flag"`
}

type DeviceBaseInfo struct {
	Id           int64  `db:"id"`
	DeviceNo     string `db:"device_no"`
	SerialId     int64  `db:"serial_id"`
	DeviceId     int64  `db:"device_id"`
	Imei         string `db:"imei"`
	Iccid        string `db:"iccid"`
	Sn           string `db:"sn"`
	ProductNo    string `db:"product_no"`
	SkuNo        string `db:"sku_no"`
	MainRomVer   string `db:"main_rom_ver"`
	SubRomVer    string `db:"sub_rom_ver"`
	TRomVer      string `db:"t_rom_ver"`
	ModuleVer    string `db:"module_ver"`
	SecKey       string `db:"seck_key"`
	AuthKey      string `db:"auth_key"`
	Password     string `db:"pasword"`
	RomConfigVer string `db:"rom_config_ver"`
	CCid         string `db:"c_cid"`
	TCid         string `db:"t_cid"`
	TestFlag     int64  `db:"test_flag"`
	Supplier     string `db:"supplier"`
	CreateTime   string `db:"create_time"`
	UpdateTime   string `db:"update_time"`
	//LastActiveTime string `db:"last_active_time"`
}

/**
拼接sql中的字段名
 */
func (dbf *DeviceBaseInfo) ToDbTagStr(Idexclude bool) string {
	of := reflect.ValueOf(dbf).Elem()
	var result = ""
	num := of.NumField()
	for i := 0; i < num; i++ {
		if Idexclude && i == 0 {
			continue
		}
		field := of.Type().Field(i)
		tag := field.Tag
		result = result + tag.Get("db") + ","
	}
	return result[0 : len(result)-1]
}

func (dbf *DeviceBaseInfo) toSqlVles(IdVleExclude bool) string {
	of := reflect.ValueOf(dbf).Elem()
	num := of.NumField()
	var result = "("
	for i := 0; i < num; i++ {
		if IdVleExclude && i == 0 {
			continue
		}
		field := of.Type().Field(i)
		switch field.Type.Kind() {
		case reflect.Int64:
			result = result + strconv.FormatInt(of.Field(i).Int(), 10) + ","
			break
		case reflect.String:
			vle := of.Field(i).String()
			if vle == "" {
				vle = " "
			}
			result = result + "'" + vle + "'" + ","
			break
		default:
			result = result + "'" + " " + "',"
		}
	}

	return result[0:len(result)-1] + ")"
}

func NewDeviceBaseMapper(ds *DataMysqlSourceClinet) (*DeviceBaseInfoMapper) {
	mapper := &DeviceBaseInfoMapper{}
	mapper.ds = ds
	return mapper
}

func buildDeviceBaseInfoQuerySQL(fieldType string, vle string) string {
	var normalSql = "SELECT " + (&DeviceBaseInfo{}).ToDbTagStr(false) + " FROM device_base_info WHERE "
	var sql = ""
	if "device_id" == fieldType {
		sql = "device_id = " + vle
	} else if "imei" == fieldType {
		sql = "imei = '" + vle + "'"
	} else if "device_no" == fieldType {
		sql = "device_no = '" + vle + "'"
	} else if "iccid" == fieldType {
		sql = "iccid = '" + vle + "'"
	} else {
		sql = "sn = '" + vle + "'"
	}

	return normalSql + sql
}

func (dbm *DeviceBaseInfoMapper) normalDeviceBaseInfoQuery2(sql string) ([] DeviceBaseInfo) {
	var deviceInfo [] DeviceBaseInfo
	e := dbm.ds.SqlDB.Select(&deviceInfo, sql)
	if e != nil {
		log.Println("查询失败！", e)
		return nil
	}
	if len(deviceInfo) == 0 {
		log.Println("设备不存在！")
		return nil
	}
	return deviceInfo
	//return &info
}

func (dbm *DeviceBaseInfoMapper) normalDeviceBaseInfoQuery(sql string) (*DeviceBaseInfo) {
	var deviceInfo [] DeviceBaseInfo
	e := dbm.ds.SqlDB.Select(&deviceInfo, sql)
	if e != nil {
		log.Println("查询失败！", e)
		return nil
	}
	if len(deviceInfo) == 0 {
		log.Println("设备不存在！")
		return nil
	}
	info := deviceInfo[0]
	return &info
}

func (dbm *DeviceBaseInfoMapper) QueryBySn(sn string) (*DeviceBaseInfo) {
	sql := buildDeviceBaseInfoQuerySQL("sn", sn)
	return dbm.normalDeviceBaseInfoQuery(sql)
}

func (dbm *DeviceBaseInfoMapper) QueryByIccid(iccid string) (*DeviceBaseInfo) {
	sql := buildDeviceBaseInfoQuerySQL("iccid", iccid)
	return dbm.normalDeviceBaseInfoQuery(sql)
}

func (dbm *DeviceBaseInfoMapper) QueryByImei(imei string) (*DeviceBaseInfo) {
	sql := buildDeviceBaseInfoQuerySQL("imei", imei)
	return dbm.normalDeviceBaseInfoQuery(sql)
}

func (dbm *DeviceBaseInfoMapper) QueryByDeviceNo(deviceNo string) (*DeviceBaseInfo) {
	sql := buildDeviceBaseInfoQuerySQL("device_no", deviceNo)
	return dbm.normalDeviceBaseInfoQuery(sql)
}

func (dbm *DeviceBaseInfoMapper) QueryByDeviceNo2(deviceNo string) ([] DeviceBaseInfo) {
	sql := buildDeviceBaseInfoQuerySQL("device_no", deviceNo)
	return dbm.normalDeviceBaseInfoQuery2(sql)
	//return convertRsp(query2);
}
func (dbm *DeviceBaseInfoMapper) QueryDeviceBaseInfoByDeviceId(deviceId int64) (*DeviceBaseInfo) {
	sql := buildDeviceBaseInfoQuerySQL("device_id", strconv.FormatInt(deviceId, 10))
	return dbm.normalDeviceBaseInfoQuery(sql)
}

func (dbm *DeviceBaseInfoMapper) InsertDeviceBaseInfo(info DeviceBaseInfo) (int64) {
	var sqlstr = "insert into device_base_info(" + info.ToDbTagStr(true) + ") values" + info.toSqlVles(true)
	result, e := dbm.ds.SqlDB.Exec(sqlstr)
	if e != nil {
		log.Println("insert失败！", e)
		return 0
	}
	i, er := result.RowsAffected()
	if er != nil {
		log.Println("rows failed", e)
	}
	return i
}

func (bdm *DeviceBaseInfoMapper) UpdateDeviceBaseInfo(info DeviceBaseInfo) (int64) {
	result, e := bdm.ds.SqlDB.Exec("UPDATE device_base_info "+
		"SET "+
		"device_no = ?,"+
		"product_no = ?,"+
		"sku_no = ?,"+
		"main_rom_ver = ?,"+
		"t_rom_ver = ?,"+
		"module_ver = ?,"+
		"seck_key = ?,"+
		"auth_key = ?,"+
		"pasword = ?,"+
		"rom_config_ver = ?,"+
		"c_cid = ?,"+
		"t_cid = ?,"+
		"test_flag = ?,"+
		"update_time = now(),"+
		"version = version+1 WHERE device_id = ?",
		info.DeviceNo,
		info.ProductNo,
		info.SkuNo,
		info.MainRomVer,
		info.TRomVer, info.ModuleVer, info.SecKey,
		info.AuthKey, info.Password, info.RomConfigVer, info.CCid,
		info.TCid, info.TestFlag,
		info.DeviceId)
	if e != nil {
		log.Println("更新失败！", e)
	}
	i, e := result.RowsAffected()
	if e != nil {
		log.Println("rows failed", e)
	}
	return i
}

func (bdm *DeviceBaseInfoMapper) CheckDeviceOnline(DeviceId int64) (bool) {
	var deviceStates [] DeviceState
	e := bdm.ds.SqlDB.Select(&deviceStates, "select id,device_id,online_flag from device_cabinet_state where device_id = ?", DeviceId)
	if e != nil {
		log.Println("查询失败！", e)
		return false
	}
	if len(deviceStates) == 0 {
		log.Println("设备不存在！")
		return false
	}
	info := deviceStates[0]
	return info.OnlineFlg == "N"
}
